package com.yc.psychologicalconsultant.service.impl;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yc.psychologicalconsultant.dao.QuestionDAO;
import com.yc.psychologicalconsultant.pojo.ProQuestionnaire;
import com.yc.psychologicalconsultant.pojo.Question;
import com.yc.psychologicalconsultant.pojo.Result;
import com.yc.psychologicalconsultant.service.QuestionService;
import com.yc.psychologicalconsultant.vo.Report;
import com.yc.psychologicalconsultant.vo.Variance;
import com.yc.psychologicalconsultant.vo.dto.Mood;
import jakarta.annotation.Resource;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author YC
 * @version 1.0
 */
@Service
public class QuestionServiceImpl extends ServiceImpl<QuestionDAO, Question> implements QuestionService {
    // 让星火大模型初始化文字的url
    private String textUrl = "http://127.0.0.1:5000/GetQuestionAnswer";

    private OkHttpClient client = new OkHttpClient();

    @Resource
    private RedisTemplate redisTemplate;

    // 用于操作String类型的redisTemplate
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    // 将Java对象序列化为JSON类型
    private final ObjectMapper objectMapper = new ObjectMapper();

    private static Map<String, List<Double>> moodScores = new HashMap<>();

    private static Variance resVariance = new Variance();

    // 存储问题ID和对应的用户选择
    private static Map<Integer, Integer> questionChoices = new HashMap<>();
    @Override
    public Result getQuestion(String username, int count, Mood mood) {
        if(count > 11) return Result.error("只能发送十次请求");

        // 如果是第一次进来
        if (count == 1) {
            // 1. 记录这一次的心情值
            redisTemplate.opsForValue().set(username + "+" + count,
                    new Mood(0.0, 0.0, 0.0,
                            0.0, 0.0, 0.0, 0.0), 30, TimeUnit.MINUTES);
            // 2. 把当前的问题id放入到 存储已回答过的问题的 表中
            int id = getRandom();
            redisTemplate.opsForList().rightPush(username + ":questionIds", id);
            // 如果是第一次,则把第一个问题发送给前端
            QueryWrapper<Question> wrapper = new QueryWrapper<Question>().eq("id", id);
            Question question = this.getOne(wrapper);
            return Result.success(question);
        }

        // 不是第一次进来
        // 1. 获取这一次心情的最大值
        Double curMoodScore = -1.0;
        String curMood = "";
        Double[] val = new Double[8];
        val[1] = mood.getSad();
        val[2] = mood.getDisgusted();
        val[3] = mood.getNeutral();
        val[4] = mood.getHappy();
        val[5] = mood.getFearful();
        val[6] = mood.getAngry();
        val[7] = mood.getSurprised();
        // 心情名称数组，与val数组对应
        String[] moodNames = {"","sad", "disgusted", "neutral",
                "happy", "fearful", "angry", "surprised"};
        // 遍历心情得分
        for (int i = 1; i <= 7; i++) {
            if (curMoodScore < val[i]) {
                curMoodScore = val[i];
                curMood = moodNames[i];
            }
        }

        // 2. 获取所有的list并进行遍历
        // 获取之前回答过的所有问题
        List<Integer> questionIds =
                redisTemplate.opsForList().range(username + ":questionIds", 0, -1);

        // 尝试根据心情和未回答过的条件查找问题
        QueryWrapper<Question> wrapper = new QueryWrapper<Question>().eq("tag", curMood);

        // 只有当questionIds不为空且至少包含一个元素时，才添加notIn条件
        if (questionIds != null && !questionIds.isEmpty()) {
            wrapper.notIn("id", questionIds);
        }

        // 限制查询结果为1
        wrapper.last("LIMIT 1");

        Question question = this.getOne(wrapper);

        // 如果没有相应的 则随机返回
        if(question == null) {
            wrapper = new QueryWrapper<Question>();
            if (questionIds != null && !questionIds.isEmpty()) {
                wrapper.notIn("id", questionIds);
                wrapper.last("LIMIT 1");
            }
            question = this.getOne(wrapper);
        }

        // 3. 存入redis
        redisTemplate.opsForValue().set(username + "+" + (count - 1),
                mood, 30, TimeUnit.MINUTES);
        redisTemplate.opsForList().rightPush(username + ":questionIds", question.getId());

        // 最后一次 返回总的结果
        if (count == 11) {
            return reportCreate(username);
        }
        return Result.success(question);
    }

    @Override
    public Result reportCreate(String username) {
        // 获取之前回答过的所有问题
        List<Integer> questionIds =
                redisTemplate.opsForList().range(username + ":questionIds", 0, -1);

        String message = "";

        handleFinalCount(username);
        collectUserResponses(username);
        // 之前回答的题号
        questionIds =
                redisTemplate.opsForList().range(username + ":questionIds", 0, -1);
        message = "我现在在做一个心理测评,我的基本情况:";
        ProQuestionnaire questionnaire =
                (ProQuestionnaire)redisTemplate.opsForValue().get(username + ":ProQuestionnaire");
        message += "性别:" + questionnaire.getGender() + " 婚姻状况:" +  questionnaire.getMarriage() + " 性格特型:" + questionnaire.getCharacter() + " 是否有知心朋友:" + questionnaire.getFriend() + " 是否参加社区活动:" + questionnaire.getCommunity();
        message += ",这是我回答的所有问题以及每个问题所选的选项(无 轻度 中度 偏重 严重):";
        // 获取所有的问题
        for(int i = 0 ; i < 10 ; i ++) {
            String choice = "";
            QueryWrapper<Question> wrapper1 =
                    new QueryWrapper<Question>().eq("id", questionIds.get(i));
            Question ques = this.getOne(wrapper1);
            message += ques.getName();
            switch (questionChoices.get(ques.getId()) + "") {
                case "0": choice = "无"; break;
                case "1": choice = "轻度"; break;
                case "2": choice = "中度"; break;
                case "3": choice = "偏重"; break;
                case "4": choice = "严重"; break;
            }
            message += "，我选择的是 " + choice + " ";
        }
        message += " 能根据我回答的问题, 以及相应的数据 对我的状态进行一个评估,不需要多余的话语,回复尽量多";
        // gpt返回的信息
        String json = sendToChat(message);
        // 转为String类型
        String text = json.toString();
        Report report = new Report();

        report.setText(text);
        report.setVariance(resVariance);

        delRedisData(username);
        return Result.success(report);
    }

    @Override
    public void SubmitProQuestionnaire(ProQuestionnaire proQuestionnaire) {
        redisTemplate.opsForValue().set(proQuestionnaire.getUsername() + ":ProQuestionnaire",proQuestionnaire);
    }

    private void delRedisData(String username) {
        redisTemplate.delete(username + ":questionIds");
        for (int i = 1; i <= 10; i++) {
            redisTemplate.delete(username + "+" + i);
        }
    }

    private void handleFinalCount(String username) {
        collectMoodScores(username);

        Map<String, Double> moodVariances = new HashMap<>();

        for (Map.Entry<String, List<Double>> entry : moodScores.entrySet()) {
            String mood = entry.getKey();
            List<Double> scores = entry.getValue();
            double average = calculateAverage(scores);
            double variance = calculateVariance(scores, average);
            moodVariances.put(mood, variance);
        }
        resVariance.setVarianceHappy(moodVariances.get("happy") * 100);
        resVariance.setVarianceFear(moodVariances.get("fearful") * 100);
        resVariance.setVarianceSad(moodVariances.get("sad") * 100);
        resVariance.setVarianceDisgusted(moodVariances.get("disgusted") * 100);
        resVariance.setVarianceNetural(moodVariances.get("neutral") * 100);
        resVariance.setVarianceFear(moodVariances.get("angry") * 100);
        resVariance.setVarianceSurprised(moodVariances.get("surprised") * 100);
    }

    private void collectUserResponses(String username) {
        // 从Redis中收集数据
        for (int i = 1; i <= 10; i++) {
            Mood mood = (Mood) redisTemplate.opsForValue().get(username + "+" + i);
            if (mood != null) {
                // 从mood中获取相关参数放入map集合中
                questionChoices.put(mood.getQuestionId(), mood.getChoice());
            }
        }
    }


    private double calculateAverage(List<Double> values) {
        double sum = 0.0;
        for (double value : values) {
            sum += value;
        }
        return sum / values.size();
    }

    private double calculateVariance(List<Double> values, double average) {
        double varianceSum = 0.0;
        for (double value : values) {
            varianceSum += Math.pow(value - average, 2);
        }
        return varianceSum / values.size();
    }


    // 收集所用的心情分数到一个Map集合中
    private void collectMoodScores(String username) {
        // 初始化每种心情的列表
        String[] moods = {"sad", "disgusted", "neutral", "happy", "fearful", "angry", "surprised"};
        for (String mood : moods) {
            moodScores.put(mood, new ArrayList<>());
        }

        // 从Redis中收集心情分数
        for (int i = 1; i <= 10; i++) {
            Mood mood = (Mood) redisTemplate.opsForValue().get(username + "+" + i);
            if (mood != null) {
                moodScores.get("sad").add(mood.getSad());
                moodScores.get("disgusted").add(mood.getDisgusted());
                moodScores.get("neutral").add(mood.getNeutral());
                moodScores.get("happy").add(mood.getHappy());
                moodScores.get("fearful").add(mood.getFearful());
                moodScores.get("angry").add(mood.getAngry());
                moodScores.get("surprised").add(mood.getSurprised());
            }
        }
    }


    public int getRandom() {
        // 生成1到90之间的随机整数
        return new Random().nextInt(90) + 1; // nextInt(90) 返回0到89之间的随机数，加1后变为1到90
    }

    public String sendToChat(String message) {
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(30, TimeUnit.SECONDS)
                .readTimeout(30, TimeUnit.SECONDS)
                .build();
        String res = null;
        JSONObject resultBody = JSONUtil.createObj()
                .put("role", "user")
                .put("content", message);
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json;charset=utf-8"),resultBody.toString());
        // 发送给chat
        Request request = new Request.Builder()
                .url(textUrl)
                .post(requestBody)
                .build();
        try {
            Response response = client.newCall(request).execute();
            // 获得的内容
            res =  response.body().string();
            System.out.println(res);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return res;
    }
}
